#include"myshell.h"

using namespace std;

//全局变量
//将解析的字符串放入字符串数组中
char* gargv[ARGS] = {NULL};
int gargc = 0;//统计数据个数

//退出码的记录
int lastcode= 0;

//保存当前shell进程的工作路径
char pwd[1024];

static std::string GetUserName()
{
    string name = getenv("USER");
    return name.empty() ? "None" : name;
}

static std::string GetHostName()
{
    string hostname = getenv("HOSTNAME");
    return hostname.empty()? "None" : hostname;
}

static std::string GetPwd()
{
    //string pwd = getenv("PWD");
    //return pwd.empty()? "None" : pwd;
    //环境变量的变化，可能会依赖于进程，pwd 需要shell 自己更新环境变量的值
    char temp[1024];
    getcwd(temp,sizeof(temp));//直接使用系统调用获取pwd
    //将获得的结果写入pwd 之中
    snprintf(pwd,sizeof(pwd) , "PWD=%s", temp);
    putenv(pwd);//再将pwd 放入环境变量中

    //获取最后一个路径
    string pwd_lable = temp;
    string pathsep = "/";
    //利用rfind 和 substr
    auto pos = pwd_lable.rfind(pathsep);
    if(pos == string::npos)//没有找到
    {
        return "Nome";
    }
    pwd_lable = pwd_lable.substr(pos+pathsep.size());
    return pwd_lable.empty() ? "/" : pwd_lable;
}

//获取家路径
static string GetHomePath()
{
    string homepath = getenv("HOME");
    return homepath.empty() ? "None" : homepath;
}

void PrintCommandPrompt()
{
    string user = GetUserName();
    string hostname = GetHostName();
    string pwd = GetPwd();
    printf("[%s@%s %s]# ", user.c_str(), hostname.c_str(), pwd.c_str());
}

//获取用户的键盘输入
bool GetCommandString(char cmd_str_buff[], int len)
{
    if(cmd_str_buff == NULL || len<=0 )
        return false;

        char * res = fgets(cmd_str_buff, len , stdin);
        if(res == NULL) return false;

        //因为fgets 会获取到 \n
        cmd_str_buff[strlen(cmd_str_buff)-1] = 0;
        return strlen(cmd_str_buff)-1 ==0 ? false : true;
}

//解析用户输入的字符串
bool ParseCommandString(char cmd[])
{
    //判断数组不为空
    if(cmd==NULL) return false;
    //可以在函数内部用#define
    #define SEP " "
    //将解析得到的字符放入全局的字符串数组中
    gargv[gargc++] = strtok(cmd , SEP);
    //最后一个需要放NULL
    while((bool)(gargv[gargc++] = strtok(NULL,SEP)));
    gargc--;

//#define DEBUG
#ifdef DEBUG
    printf("gargc:%d\n", gargc);
    printf("---------------------------------\n");
    for(int i = 0;i<gargc;i++)
    {
        printf("gargv[%d]:%s\n",i , gargv[i]);
    }
    printf("----------------------------------\n");
    for(int i = 0; gargv[i];i++)
    {
        printf("gargv[%d]:%s\n",i ,gargv[i]);
    }
#endif

    return true;
}

//初始化全局变量
void InitGlobal()
{
    gargc = 0;
    memset(gargv , 0 , sizeof(gargv));
}

//创建子进程、替换代码实现命令行功能
void ForkAndExec()
{
    pid_t id = fork();
    if(id<0)//创建子进程失败
    {
        perror("fork");
        return;
    }
    else if(id ==0)//子进程
    {
        //替换程序
        execvp(gargv[0], gargv);
        exit(0);
    }
    else
    {
        //父进程
        //获取退出码
        int status = 0;
        pid_t rid = waitpid(id , &status,0);//父进程阻塞等待子进程
        if(rid >0)//等待成功
        {
            //记录当前退出码
            lastcode = WEXITSTATUS(status);
        }
    }
}

bool BuiltInCommandExec()
{
    //内建命令就是shell 自己要执行的命令
    string cmd = gargv[0];
    bool ret = false;
    if(cmd == "cd")
    {
        if(gargc == 2)
        {
            string target = gargv[1];
            if(target == "~")
            {
                ret = true;
                //更该父进程的路径
                chdir(GetHomePath().c_str());
            }
            else
            {
                ret = true;
                chdir(gargv[1]);
            }
        }
        else if(gargc == 1)
        {
            ret = true;
            chdir(GetHomePath().c_str());
        }
        else
        {
        }
    }
    else if(cmd == "echo")
    {
        if(gargc == 2)
        {
            string args = gargv[1];
            if(args[0]=='$')
            {
                if(args[1]=='?')
                {
                    printf("lastcode:%d\n",lastcode);
                    lastcode = 0;
                    ret = true;
                }
                else 
                {
                    const char* name = &args[1];
                    printf("%s\n",getenv(name));
                    lastcode = 0;
                    ret = true;
                }
            }
            else
            {
                printf("%s\n",args.c_str());
                ret = true;
            }
        }
    }
    return ret;
}

                    
